;  PROGRAM:  PHELP
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.2 (12 JULY 1980)
;  PREVIOUS VERSIONS:  1.1 (8 JUNE 1980), 1.0 (5 JUNE 1980)

;
;  PHELP -- Print contents of .HLP file on printer.  The format
;    of this command is --
;		PHELP filename header
;    where 'filename' is the name of the file 'filename.HLP' on the currently-
;    logged in disk.  The printed listing produced by this command is numbered
;    with the name of the help file and header at the top of each page.
;

;  External References --
	EXT	EN	; EXCHANGE NYBBLES OF A
	EXT	LOUT	; LIST OUTPUT
	EXT	PRINT	; STRING PRINT ROUTINE
	EXT	CONDIN	; CONDITIONAL INPUT
	EXT	CRLF	; NEW LINE
	EXT	CIN	; CONSOLE INPUT
	EXT	FI$OPEN	; FILE OPEN
	EXT	F$GET	; GET

;  CP/M and other miscellaneous equates
CPM	EQU	0	; CP/M WARM BOOT
BUFF	EQU	80H	; INPUT LINE BUFFER
FCB	EQU	5CH	; CP/M FCB
FCBTY	EQU	FCB+9	; CP/M FILE TYPE IN FCB
TAB	EQU	9	; <TAB>
LF	EQU	0AH	; <LF>
FF	EQU	0CH	; <FF>
CR	EQU	0DH	; <CR>
ESC	EQU	1BH	; <ESC>
CTRLC	EQU	'C'-40H	; CTRL-C
EOF	EQU	'Z'-40H	; CTRL-Z = EOF
COLON	EQU	':'	; COLON CHARACTER

;  NUMBER OF LINES PER PAGE
LPG	EQU	51	; 51 LINES PER PAGE
TPG	EQU	40	; 40 LINES OF TEXT PER PAGE

START:
;
;  EXTRACT HEADER FROM COMMAND LINE
;
	LXI	H,BUFF	; GET INPUT LINE
	PUSH	H	; SAVE PTR
	MOV	A,M	; GET BYTE COUNT
	ADD	L	; PT TO EOL
	MOV	L,A
	INR	L	; HL PT TO EOL
	MVI	M,0	; LINE TERMINATED BY ZERO
	LXI	D,HBUF	; PT TO HEADER BUFFER
	POP	H	; GET PTR TO HEADER
	INX	H	; PT TO 1ST CHAR
HEADING:
	MOV	A,M	; GET BYTE OF HEADER
	STAX	D	; PLACE IN HEADER BUFFER
	INX	H	; PT TO NEXT CHAR
	INX	D
	ORA	A	; DONE IF ZERO
	JNZ	HEADING

;
;  PLACE DEFAULT FILE TYPE IN FCB
;
	LXI	H,FTYPE	; PT TO FILE TYPE
	LXI	D,FCBTY	; PT TO FCB ENTRY
	MVI	B,3	; 3 BYTES
MTYPE:
	MOV	A,M	; GET BYTE
	STAX	D	; PUT BYTE
	INX	H	; PT TO NEXT
	INX	D
	DCR	B	; COUNT DOWN
	JNZ	MTYPE
;
;  OPEN FILE FOR INPUT
;    AUTOMATIC ABORT TO CP/M IF ERROR
;
	LXI	D,FCB	; PT TO FCB
	CALL	FI$OPEN	; OPEN FILE FOR INPUT

;
;  PRINT OPENING MESSAGE AND OPTIONALLY ABORT
;
	CALL	PRINT
	DB	'PHELP Version 1.2'
	DB	CR,LF
	DB	'  Please set Top of Form'
	DB	CR,LF
	DB	'  Type Ctrl-C or <ESC> to abort or anything else to cont - ',0
	CALL	CIN	; GET INPUT
	CPI	ESC
	JZ	ABORT
	CPI	CTRLC
	JZ	ABORT
	CALL	CRLF	; NEW LINE
;
;  SET PAGE NUMBER, LINE COUNT, AND PRINT HEADER
;
	XRA	A	; A=0
	STA	PNUM	; SET PAGE NUMBER TO ZERO
	STA	CCNT	; SET CHAR COUNT IN LINE
	MVI	A,TPG	; SET LINES OF TEXT PER PAGE
	STA	LINES	; SET LINE COUNT
	CALL	PHDR	; PRINT HEADER
;
;  GET FIRST CHAR -- SPECIAL CASE
;
	CALL	F$GET
	JC	DONE	; DONE IF CARRY
	ANI	7FH	; MASK MSB
;
;  MAIN LOOP -- PRINT CHAR IN A, GET NEXT CHAR, AND PROCESS
;
PHELP:
	CPI	TAB	; <TAB>?
	JZ	SPTAB
	CPI	FF	; <FF>?
	JZ	GETCH
	CALL	LOUT	; SEND TO LIST DEVICE
	LDA	CCNT	; INCR CHAR CNT
	INR	A
	STA	CCNT
;
;  GET NEXT CHAR
;
GETCH:
	CALL	CONDIN	; CHECK FOR INTERRUPT
	JZ	GETCH1	; CONTINUE IF NO CHAR
	CPI	ESC	; ABORT IF <ESC>
	JZ	ABORT
	CPI	CTRLC	; ABORT IF CTRL-C
	JNZ	GETCH1
;  INTERRUPT -- ABORT
ABORT:
	CALL	EJECT	; EJECT PAGE
	CALL	PRINT	; PRINT ABORT MESSAGE ON CON:
	DB	CR,LF,'PHELP Aborted -- Returning to CP/M',0
	JMP	CPM	; WARM BOOT
;  GET NEXT CHAR
GETCH1:
	CALL	F$GET	; GET CHAR
	JC	DONE	; DONE IF CARRY
	ANI	7FH	; MASK MSB
	CPI	EOF	; DONE?
	JZ	DONE
	CPI	FF	; IGNORE <FF>
	JZ	GETCH1
;
;  TEST FOR NEW LINE AND PROCESS IF SO
;
	CPI	LF	; NEW LINE?
	JNZ	PHELP	; CONTINUE IF NOT
	CALL	LOUT	; SEND <LF>
	XRA	A	; A=0
	STA	CCNT	; RESET CHAR CNT
	CALL	F$GET	; GET NEXT CHAR
	JC	DONE	; EOF
	ANI	7FH	; MASK MSB
	CPI	EOF	; DONE?
	JZ	DONE
	PUSH	PSW	; SAVE NEXT CHAR
	CPI	COLON	; IS FIRST CHAR OF NEXT LINE A COLON?
	JZ	PAGE	; PAGE IF SO
	LDA	LINES	; DECREMENT LINE COUNT
	DCR	A
	STA	LINES
	JZ	PAGEOV	; PAGE IF LINE COUNT DROPS TO ZERO
	POP	PSW	; GET NEXT CHAR TO PRINT
	JMP	PHELP	; CONTINUE
;
;  PROCESS <TAB>
;
SPTAB:
	MVI	A,' '	; PRINT <SP>
	CALL	LOUT
	LDA	CCNT	; INCR CHAR CNT
	INR	A
	STA	CCNT
	ANI	7	; DONE?
	JNZ	SPTAB
	JMP	GETCH
;
;  NEW PAGE
;
PAGEOV:	MVI	A,1	; A=1
	STA	LINES	; PAGE OVERFLOW -- COMPENSATE FOR EJECT
PAGE:	CALL	EJECT	; EJECT PAGE
	CALL	PHDR	; PRINT HEADER
	POP	PSW	; GET NEXT CHAR TO PRINT
	JMP	PHELP	; CONTINUE
;
;  DONE WITH PHELP PROGRAM
;
DONE:
	CALL	EJECT	; NEW PAGE
	JMP	CPM	; RETURN TO CP/M

;
;  EJECT PAGE
;
EJECT:
	LDA	LINES	; ANY LINES LEFT?
	ADI	LPG-TPG-1	; ADD NORMAL LINE COUNT
	MOV	B,A	; COUNT IN B
	MVI	A,CR	; <CR>
	CALL	LOUT
	MVI	A,LF	; <LF>
EJECT1:
	CALL	LOUT	; <LF> DOWN PAGE
	DCR	B	; COUNT DOWN
	JNZ	EJECT1
	MVI	A,TPG	; RESET LINE COUNT
	STA	LINES
	RET
;
;  PRINT HEADER AT TOP OF PAGE
;
PHDR:
;  PRINT 'PAGE'
	LXI	H,PGMS	; PRINT PAGE NUMBER
	CALL	LSTR	; PRINT ON PRINTER
;  PRINT PAGE NUMBER
	LDA	PNUM	; INCREMENT PAGE NUMBER
	ADI	1	; BCD
	DAA		; ADJUST
	STA	PNUM
	PUSH	PSW	; SAVE PAGE NUMBER
	CALL	EN	; EXCHANGE NYBBLES
	ANI	0FH	; MASK LOW
	JZ	LDBLK	; LEADING BLANK
	CALL	LNUM	; PRINT A AS A DIGIT
	JMP	PHDR1
LDBLK:
	MVI	A,' '	; PRINT LEADING <SP> IF PAGE NUMBER LT 10
	CALL	LOUT
PHDR1:
	POP	PSW	; GET PAGE NUMBER
	ANI	0FH	; MASK LOW
	CALL	LNUM	; PRINT A AS A DIGIT
;  PRINT SYSTEM HEADER
	LXI	H,TITLE	; PRINT SYSTEM HDR
	CALL	LSTR
;  PRINT USER HEADER
	LXI	H,HBUF	; PRINT BUFFER CONTENTS
	CALL	LSTR
;  2 LINES
	MVI	A,CR	; SKIP DOWN
	CALL	LOUT
	MVI	A,LF	; <LF>
	CALL	LOUT
	CALL	LOUT
	LDA	LINES	; DECR LINE COUNT
	DCR	A
	DCR	A
	STA	LINES
	RET
;
;  PRINT A AS A DECIMAL DIGIT
;
LNUM:
	ADI	'0'	; CONVERT TO ASCII
	JMP	LOUT	; PRINT
;
;  PRINT STRING PTED TO BY HL ENDING IN 0 ON LST:
;
LSTR:
	MOV	A,M	; GET CHAR
	ORA	A	; ZERO=DONE
	RZ
	CALL	LOUT	; PRINT IT
	INX	H	; PT TO NEXT CHAR
	JMP	LSTR

;
;  BUFFERS AND MESSAGES
;
CCNT:	DS	1	; LINE CHAR CNT
PNUM:	DS	1	; PAGE NUMBER
LINES:	DS	1	; LINE COUNT

FTYPE:	DB	'HLP'	; FILE TYPE

PGMS:	DB	'Page Number ',0
TITLE:	DB	' -- HELP File Listing: ',0
HBUF:	DS	256	; HEADER BUFFER
	DB	0	; END OF PROGRAM

	END
